package com.donghua.service;

import com.alibaba.fastjson.JSON;
import com.donghua.dao.UserMapper;
import com.donghua.dto.EmailDTO;
import com.donghua.entity.LoginTicket;
import com.donghua.entity.User;
import com.donghua.enums.StatusCodeEnum;
import com.donghua.exception.BizException;
import com.donghua.util.CommunityUtil;
import com.donghua.util.RandomNickName;
import com.donghua.util.RedisKeyUtil;
import com.donghua.vo.UserVO;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.donghua.constant.MQPrefixConst.EMAIL_EXCHANGE;
import static com.donghua.constant.RedisPrefixConst.CODE_EXPIRE_TIME;
import static com.donghua.constant.RedisPrefixConst.USER_CODE_KEY;
import static com.donghua.enums.StatusCodeEnum.REPEAT_ERROR;
import static com.donghua.util.CommunityUtil.getRandomCode;

/**
 * @author Cai Lideng
 * @date 2022年04月23日 下午2:53
 * @description
 */
@Service
public class LoginService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisService redisService;

    @Autowired UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    public void sendCode(String username) {
        // 校验账号是否合法
        if (!checkEmail(username)) {
            throw new BizException(StatusCodeEnum.VALID_ERROR.getCode(), "请输入正确邮箱");
        }
        // 生成六位随机验证码发送
        String code = getRandomCode();
        // 发送验证码
        EmailDTO emailDTO = EmailDTO.builder()
                .email(username)
                .subject("验证码")
                .content("您的验证码为 " + code + " 有效期15分钟，请不要告诉他人哦！")
                .build();
        rabbitTemplate.convertAndSend(EMAIL_EXCHANGE, "*", new Message(JSON.toJSONBytes(emailDTO), new MessageProperties()));
        // 将验证码存入redis，设置过期时间为15分钟
        redisService.set(USER_CODE_KEY + username, code, CODE_EXPIRE_TIME);
    }

    public void register(@NotNull UserVO user) {
        // 校验账号是否合法
        if (checkUser(user)) {
            throw new BizException(REPEAT_ERROR.getCode(), REPEAT_ERROR.getMsg());
        }
        // 新增用户账号
        User userAdd = new User();
        userAdd.setNickName(user.getNickName());
        userAdd.setUsername(user.getUsername());
        System.out.println(user.getUsername());
        userAdd.setSalt(CommunityUtil.generateUUID().substring(0, 5));
        userAdd.setPassword(CommunityUtil.md5(user.getPassword() + userAdd.getSalt()));
        userAdd.setType(0);
        userAdd.setStatus(0);
        userAdd.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));
        userAdd.setCreateTime(new Date());
        userMapper.insertUser(userAdd);
    }

    private boolean checkEmail(String username) {
        String rule = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";
        //正则表达式的模式 编译正则表达式
        Pattern p = Pattern.compile(rule);
        //正则表达式的匹配器
        Matcher m = p.matcher(username);
        //进行正则匹配
        return m.matches();
    }

    private Boolean checkUser(UserVO user) {
        if (!user.getCode().equals(redisService.get(USER_CODE_KEY + user.getUsername()))) {
            throw new BizException(StatusCodeEnum.VALID_CODE_ERROR.getCode(), "验证码错误！");
        }
        //查询用户名是否存在
        User userByName = userService.findUserByName(user.getUsername());
        return userByName != null;
    }

    public Map<String, Object> login(String username, String password, int expiredSeconds) {
        Map<String, Object> map = new HashMap<>();
        // 验证账号
        User user = userMapper.selectByName(username);
        if (user == null) {
            map.put("usernameMsg", "该账号不存在!");
            return map;
        }
        // 验证密码
        password = CommunityUtil.md5(password + user.getSalt());
        if (!user.getPassword().equals(password)) {
            map.put("passwordMsg", "密码不正确!");
            return map;
        }
        // 生成登录凭证
        LoginTicket loginTicket = new LoginTicket();
        loginTicket.setUserId(user.getId());
        loginTicket.setTicket(CommunityUtil.generateUUID());
        loginTicket.setStatus(0);
        loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));
        String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket());
        redisTemplate.opsForValue().set(redisKey, loginTicket, expiredSeconds, TimeUnit.SECONDS);
        map.put("ticket", loginTicket.getTicket());
        return map;
    }

    public void logout(String ticket) {
        String redisKey = RedisKeyUtil.getTicketKey(ticket);
        LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey);
        loginTicket.setStatus(1);
        redisTemplate.opsForValue().set(redisKey, loginTicket);
    }
}
